import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';

class RfidBleManager {
  BluetoothDevice? _device;
  // 读取数据
  BluetoothCharacteristic? _rxCharacteristic;
  // 发送写入数据
  BluetoothCharacteristic? _txCharacteristic;
  // FR30这样只扫描设备
  BluetoothCharacteristic? _frCharacteristic;
  StreamSubscription? _connectionSub;
  StreamSubscription? _charSubscription;
  StreamSubscription? _frCharSubscription;
  StreamSubscription<BluetoothAdapterState>? _adapterStateStateSub;
  Timer? _serviceDiscoveryTimer;
  bool _isConnected = false;
  int _retryCount = 0;
  final List<BluetoothDevice> _scannedDevices = [];
  Function(bool)? onStateChanged;

  // UUID定义
  static const String UART_SERVICE_UUID =
      "0000FFF0-0000-1000-8000-00805F9B34FB";
  static const String TX_UUID = "0000FFF2-0000-1000-8000-00805F9B34FB";
  static const String RX_UUID = "0000FFF1-0000-1000-8000-00805F9B34FB";
  static const String CLIENT_CONFIG_UUID =
      "00002902-0000-1000-8000-00805F9B34FB";

  bool get isConnected => _isConnected;
  set isConnected(bool value) {
    _isConnected = value;
    onStateChanged?.call(_isConnected);
  }

  List<BluetoothDevice> get scannedDevices => _scannedDevices;
  BluetoothCharacteristic? get rxCharacteristic => _rxCharacteristic;
  BluetoothCharacteristic? get txCharacteristic => _txCharacteristic;
  bool get isGW => true;
  BluetoothDevice? get device => _device;
  Stream<List<int>>? get inputStream => null; // 如有数据流可补充
  Stream<BluetoothAdapterState> get adapterState =>
      FlutterBluePlus.adapterState;
  Function(List<int>, {bool isBacker})? _handleData;
  // 判断是否是背夹设备
  bool _isBackPower = true;

  Future<void> initialize(Function(List<int>, {bool isBacker}) handleData,
      Function(bool)? stateChanged) async {
    _handleData = handleData;
    onStateChanged = stateChanged;
    _adapterStateStateSub = FlutterBluePlus.adapterState.listen((state) {
      if (state == BluetoothAdapterState.off) {
        isConnected = false;
      }
    });
  }

  void onDispose() {
    _adapterStateStateSub?.cancel();
    _connectionSub?.cancel();
  }

  Future<bool> connectDevice(BluetoothDevice device) async {
    try {
      _device = device;
      _retryCount = 0;
      await device.connect();
      _connectionSub?.cancel();
      _connectionSub = device.connectionState.listen((state) {
        if (state == BluetoothConnectionState.connected) {
          _startServiceDiscovery();
        } else if (state == BluetoothConnectionState.disconnected) {
          isConnected = false;
          _cleanupConnection();
        }
      });
      return true;
    } catch (e) {
      isConnected = false;
      return false;
    }
  }

  void _startServiceDiscovery() {
    _serviceDiscoveryTimer?.cancel();
    _serviceDiscoveryTimer =
        Timer.periodic(const Duration(milliseconds: 500), (timer) {
      if (_retryCount++ < 10) {
        _discoverServices();
      } else {
        timer.cancel();
        if (_retryCount >= 4) {
          disconnect();
          Future.delayed(const Duration(milliseconds: 400), () {
            reconnect();
          });
        }
      }
    });
  }

  Future<void> _discoverServices() async {
    if (_device == null) return;
    try {
      List<BluetoothService> services = [];
      try {
        services = await _device?.discoverServices() ?? [];
      } catch (e) {
        throw Exception('发现服务失败: $e');
      }
      if (services.isEmpty) {
        throw Exception('没有找到任何服务');
      }

      BluetoothService? bleService;
      for (final service in services) {
        try {
          if (service.uuid.str128.toString().toUpperCase() ==
              UART_SERVICE_UUID) {
            bleService = service;
            break;
          }
        } catch (_) {
          continue;
        }
      }

      if (bleService == null) {
        throw Exception('未找到UART服务 (UUID: $UART_SERVICE_UUID)');
      }
      // 只读的设备
      if (device?.platformName.contains("RF") == true) {
        List<BluetoothService> rfService = _findRFServices(services);
        // RF30设备：只读数据
        _frCharacteristic =
            _findRFCharacteristic(rfService.first, CLIENT_CONFIG_UUID);
        // 只读订阅数据
        _isBackPower = false;
        debugPrint("不是背夹设备");
        await _frCharacteristic?.setNotifyValue(true);
        _frCharSubscription?.cancel();
        _frCharSubscription =
            _frCharacteristic?.onValueReceived.listen((value) {
          // 这里应有回调或数据处理
          debugPrint('isBaker $_isBackPower');
          _handleData?.call(value, isBacker: _isBackPower);
        });
      } else {
        // 背夹设备：能读写
        _rxCharacteristic =
            _characteristic(bleService.characteristics, TX_UUID);
        // 背夹设备：能读写数据
        _txCharacteristic =
            _characteristic(bleService.characteristics, RX_UUID);

        await _txCharacteristic?.setNotifyValue(true);
        if (_rxCharacteristic == null || _txCharacteristic == null) {
          return;
        }
        _charSubscription?.cancel();
        _charSubscription = _txCharacteristic?.onValueReceived.listen((value) {
          // 这里应有回调或数据处理
          _handleData?.call(value);
        });
      }

      _serviceDiscoveryTimer?.cancel();
      isConnected = true;
    } catch (e) {
      // 发现服务失败
      _serviceDiscoveryTimer?.cancel();
      isConnected = false;
    }
  }

  List<BluetoothService> _findRFServices(List<BluetoothService> allServices) {
    return allServices.where((service) {
      return service.characteristics.any((characteristic) {
        final notify = characteristic.properties.notify;
        final serviceUUID =
            service.uuid.str128.toUpperCase() == UART_SERVICE_UUID;
        final hasDescriptor = characteristic.descriptors.any((descriptor) =>
            descriptor.uuid.str128.toUpperCase() == CLIENT_CONFIG_UUID);

        return serviceUUID && hasDescriptor && notify;
      });
    }).toList();
  }

  BluetoothCharacteristic? _findRFCharacteristic(
      BluetoothService service, String uuid) {
    return service.characteristics.firstWhere(
      (c) =>
          c.properties.notify &&
          c.descriptors.any((d) => d.uuid.str128.toUpperCase() == uuid),
    );
  }

  BluetoothCharacteristic? _characteristic(
      List<BluetoothCharacteristic> characteristics, String uuid) {
    if (characteristics.isEmpty || uuid.isEmpty) return null;

    final upperUuid = uuid.toUpperCase();
    for (final characteristic in characteristics) {
      try {
        if (characteristic.uuid.str128.toString().toUpperCase() == upperUuid) {
          return characteristic;
        }
      } catch (_) {
        continue;
      }
    }
    return null;
  }

  Future<void> reconnect() async {
    if (_device != null) {
      await connectDevice(_device!);
    }
  }

  void _cleanupConnection() {
    _connectionSub?.cancel();
    _charSubscription?.cancel();
    _serviceDiscoveryTimer?.cancel();
    _rxCharacteristic = null;
    _txCharacteristic = null;
    _isBackPower = true;
  }

  Future<void> disconnect() async {
    _cleanupConnection();
    if (_device != null) {
      await _device!.disconnect();
      _device = null;
    }
    _isConnected = false;
  }

  Future<void> connect() async {
    if (_device != null) {
      await connectDevice(_device!);
    }
  }
}
